/**
 * 
 */
package zeroj.web.dispatch;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import zeroj.resource.ResourceInjector;
import zeroj.web.action.IAction;
import zeroj.web.core.Interceptor;
import zeroj.web.core.Scope;
import zeroj.web.format.Format;
import zeroj.web.format.FormatHelper;
import zeroj.web.format.IFormater;
import zeroj.web.validator.IValidator;
import zeroj.web.validator.Validate;
import zeroj.web.validator.ValidatorHelper;

/**
 * @author LYL(lylsir at gmail dot com)
 *
 */
public class ActionInfo {

	private ActionHolder actionHolder = new ActionHolder(this);
	private List<Interceptor> interceptors = new ArrayList<Interceptor>();
	private String[] paramNames = new String[0];
	private Map<String, String> results = new HashMap<String, String>();
	private Map<String, Class<?>> formClasses = new HashMap<String, Class<?>>();
	private Map<String, List<IValidator>> validates = new HashMap<String, List<IValidator>>();
	private Map<String, IFormater> formats = new HashMap<String, IFormater>();
	private Class<IAction> actionClass;
	private String path = null;
	private boolean loginRequired = false;
	private String loginRole;
	private String loginUri;
	private boolean transactional = false;
	private Scope scope;
	private boolean isGetDirect = true;
	
	public List<Interceptor> getInterceptors() {
		return interceptors;
	}
	public void setInterceptors(List<Interceptor> interceptors) {
		this.interceptors = interceptors;
	}
	public String[] getParamNames() {
		return paramNames;
	}
	public String getPath() {
		return path;
	}
	public void setPath(String path) {
		this.path = path;
	}
	public boolean isLoginRequired() {
		return loginRequired;
	}
	public void setLoginRequired(boolean loginRequired) {
		this.loginRequired = loginRequired;
	}
	public String getLoginRole() {
		return loginRole;
	}
	public void setLoginRole(String loginRole) {
		this.loginRole = loginRole;
	}
	public String getLoginUri() {
		return loginUri;
	}
	public void setLoginUri(String loginUri) {
		this.loginUri = loginUri;
	}
	public boolean isTransactional() {
		return transactional;
	}
	public void setTransactional(boolean transactional) {
		this.transactional = transactional;
	}
	
	public void addResult(String key, String page) {
		
		results.put(key, page);
	}
	public String getResult(String key) {
		
		return results.get(key);
	}
	public Scope getScope() {
		return scope;
	}
	public void setScope(Scope scope) {
		this.scope = scope;
	}
	public boolean isGetDirect() {
		return isGetDirect;
	}
	public void setGetDirect(boolean isGetDirect) {
		this.isGetDirect = isGetDirect;
	}
	public void addInterceptor(Interceptor interceptor) {
		
		interceptors.add(interceptor);
	}
	public Class<IAction> getActionClass() {
		return actionClass;
	}
	public void setActionClass(Class<IAction> actionClass) {
		this.actionClass = actionClass;
		for(Validate validate : ValidatorHelper.parseValidates(actionClass))
			validates.put(validate.name, validate.validators);
		for(Format format : FormatHelper.parseFormats(actionClass))
			formats.put(format.name, format.formater);
	}
	public void addForm(String name, Class<?> formClass) {
		formClasses.put(name, formClass);
	}
	public String getParamName(int index) {
		
		if(paramNames.length <= index)
			return null;
		return paramNames[index];
	}
	public void addParamName(int index, String name) {
		
		if(index < paramNames.length)
			paramNames[index] = name;
		else {
			String[] names = new String[index + 1];
			System.arraycopy(paramNames, 0, names, 0, paramNames.length);
			paramNames = names;
			paramNames[index] = name;
		}
	}
	
	public Map<String, List<IValidator>> getValidates() {
		return validates;
	}
	public Map<String, IFormater> getFormats() {
		return formats;
	}
	public IAction getAction() {
		
		return actionHolder.getAction();
	}
	private static class ActionHolder {
		
		private final ActionInfo info;
		private IAction appAction;
		
		ActionHolder(ActionInfo info) {
			this.info = info;
		}
		
		IAction getAction() {
			
			switch(info.scope) {
			case Application:
				if(appAction == null)
					appAction = newAction();
				return appAction;
			case Session:
				
			}
			return null;
		}
		
		IAction newAction() {
			
			try {
				IAction action = info.actionClass.newInstance();
				ResourceInjector.inject(action);
				return action;
			} catch(Throwable t) {
				return null;
			}
		}
	}
}
